package com.ys.utils.http;

import com.alibaba.fastjson.JSONObject;
import com.ys.utils.spring.config.SystemError;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * 
 * @author 
 * 
 * @date:2016年4月8日上午11:51:36
 */
public final class RSAUtils {
	private static String RSA = "RSA";
	// 原秘钥
	private static final String privateKeyStr = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKPxVU4xRsIuqt7kRQRCF4RfgUaMyGFQ9WRi1tz3mpG6P3GmFfRskoSm8/PD5wxHspeBGL/8vavxHWS/20jfQY9MEZEMDNMIN7vpgE6hI8bAv+22jtl5y7Bjm5Y4yRRj586z+yefHsUGgRypSsgznDATqsNPlCC4LbSTZoKvx62fAgMBAAECgYAtkqauB9Ctph9lunrdBipXZ90d6YDCXKj6cOddoY7cN7PvOcYcnhnUujxSZQDTTxL8PqzMoctwAqSzHwosJbOpWgcLKIXRD1GfLoIGygk+QNJxwqyxgw4gkKVdmtnbkv42UBubHeGeFAobVBsUIrQ+Ca+1ujVd+4Th13Emh6uAUQJBANCzqP8Wkvzb6KbDwZj8fa4FdsJv3DHvKIp9cuTfMu1/DkL77OfWm+hz1WSpFC2xmQyDeIjfgSTCZcGDR6pUAbMCQQDJGN2+FpNilYtBmGs/97qybxwFbUGwhq2UvdJikDkF2vn3R4YgWknOp79ML5jn3ihTtmgBbX0/kpQJIFRGe/ZlAkAr2BKAxHVMucY+gpGBWkns7Sjt4CIaO2wA7Cne+yTvz+lnGRXD/snyI6OI6hxbHRxSDKyd1JaE6nIGHVZI6i0RAkArJHaODXHZOJQDopt/wboABe5RC7uID5y1yHOWSbKyGuR9tI6F6ljjSQG1apC3TeYA76UoiUDRnrS7sH/kDzwxAkB1flszYFH0To4gD/8tCka0DHq+9+nQb2zZrkyubCGKH5aY2MkJd3rQJz+anGGgcY1slb/Er/I3z4KBHfTPjfvp";
	private static final String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCs42UAguMRyn1KpUoJRPVJmf9RKcfmcGQIq69mfkRs+Dr9lI/6LJmSp86ILCM/L6QVHjODJqZVObgkApELdTo88IvoVx056S22Eg+YvTcSI2W0jOfUIqefs5PW2+YLzWGyynrDOfwQkBd4/whTcv6FZ9EI2RTBNyycovF2AiPoLQIDAQAB";


	private static final int MAX_ENCRYPT_BLOCK = 117;

	private static final int MAX_DECRYPT_BLOCK = 256;

	
	public static byte[] encryptData(byte[] data, PublicKey publicKey) {
		try {
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);

			int inputLen = data.length;
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			int offSet = 0;
			byte[] cache;
			int i = 0;
			while (inputLen - offSet > 0) {
				if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
					cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
				} else {
					cache = cipher.doFinal(data, offSet, inputLen - offSet);
				}
				out.write(cache, 0, cache.length);
				i++;
				offSet = i * MAX_ENCRYPT_BLOCK;
			}
			byte[] encryptedData = out.toByteArray();
			out.close();
			return encryptedData;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) {
		try {
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			cipher.init(Cipher.DECRYPT_MODE, privateKey);

			int inputLen = encryptedData.length;
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			int offSet = 0;
			byte[] cache;
			int i = 0;
			while (inputLen - offSet > 0) {
				if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
					cache = cipher.doFinal(encryptedData, offSet,
							MAX_DECRYPT_BLOCK);
				} else {
					cache = cipher.doFinal(encryptedData, offSet, inputLen
							- offSet);
				}
				out.write(cache, 0, cache.length);
				i++;
				offSet = i * MAX_DECRYPT_BLOCK;
			}
			byte[] decryptedData = out.toByteArray();
			out.close();
			return decryptedData;
		} catch (Exception e) {
			return null;
		}
	}

	public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
		try {
			byte[] buffer = Base64Utils.decode(publicKeyStr);
			KeyFactory keyFactory = KeyFactory.getInstance(RSA);
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
			return (RSAPublicKey) keyFactory.generatePublic(keySpec);
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此算法");
		} catch (InvalidKeySpecException e) {
			throw new Exception("公钥非法");
		} catch (NullPointerException e) {
			throw new Exception("公钥数据为空");
		}
	}

	
	public static PrivateKey loadPrivateKey(String privateKeyStr)
			throws Exception {
		try {
			byte[] buffer = Base64Utils.decode(privateKeyStr);
			// X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
			KeyFactory keyFactory = KeyFactory.getInstance(RSA);
			return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此算法");
		} catch (InvalidKeySpecException e) {
			throw new Exception("私钥非法");
		} catch (NullPointerException e) {
			throw new Exception("私钥数据为空");
		}
	}

	//字段解密
	public static String  decryptField(Object param){
		String deStr = "";
		try{
			//log.debug("字段解密前。。。。"+toJson(param));
			PrivateKey privateKey = loadPrivateKey(privateKeyStr);
			StringBuilder message = new StringBuilder(param.toString());
			byte[] bb = Base64Utils.decode(message.toString());
			deStr = new String(decryptData(bb, privateKey), "UTF-8");
		}catch (Exception e){
			SystemError.wrapBs("500","数据异常");
		}
		//log.debug("字段解密后。。。。"+toJson(deStr));
		return deStr;
	}

	//字段加密
	public static String encryptField(Object param) throws Exception {
		//log.debug("字段加密前。。。。"+toJson(param));
		PublicKey publicKey = loadPublicKey(publicKeyStr);
		byte[] bb = encryptData(toJson(param).toString().getBytes("UTF-8"), publicKey);
		String encryptData = Base64Utils.encode(bb);
		//log.debug("字段加密后。。。。"+toJson(encryptData));
		return encryptData;
	}

	public static Object toJson(Object obj) {
		return JSONObject.parse(JSONObject.toJSONString(obj));
	}
	
	public static void main(String[] args) throws Exception {
	    /*String privateKeyStr = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIitE3zf4m69Zn3iItWr4K8zSmsfOz7+2S5pQcwCUVHZhU2612qO5WMpGX+jeIeS1vhfH6BUs/WgQI7PdFDoHqIdSzBwgv3nYF2cbumoa7xkgQvo5X+i6EjVBde+Ug75sDOqJwSEhbKhxAi2kVVPSIy/lB1bZRgrZ+FQ6aY4C+rVAgMBAAECgYBF/iyOtLDm+UO1j8s7FWxZDLE9rp7OogBizjCN41n1yqmDpv2OamN6pp+SSAr/kulYBI7Tssz+KvUkrYTpshWNO3fFqp0ynzROPVuDdoIlCakpJR7XtHOFUhrriF/p16QXlp+NclnmlDq7M3yj2bZQzltfc/yNmTQwq3UNuj0ouQJBAM2DirRM4mZMcYd+9K9+EbpSOj4tjPqZXsKfpGNmdFQVB5tgPhUz6VOjScygffTXToyZdgtBJHNKJ+QhTv7G8JcCQQCqQG47uWaabNWos9g3Q8V0ZBmMRNrw1o0nhqqwGFyTh3ADzJY+ckIFD1/PcYZvrTFJuTWmfFRVSyfccEcelMFzAkEAhqTM5g2NMsqYgtY5hxSIltKyl/QN7k03WTlwYTNJuaDBiBmI8yk8j/BmNGtdumCpdNJCFWOLdwE5m2v7Lk62ZwJAPZSqiq3IAAlnyuqqRWsdC7l9SDBLpRtl2SsrqCBXtAEkMiuZGKNJX/0soaMlhlV14327eymzc1qI44I1J0mVIwJBAKqalVSWOrHbC9dO4zgZkuoCWSSOlMX9mG+u+82de087VHT/2AGlZuJ83lq/jqsgehFzh6zCxh8EeCeSZIUVvcQ=";
	    PrivateKey PrivateKey = loadPrivateKey(privateKeyStr);
	    String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIrRN83+JuvWZ94iLVq+CvM0prHzs+/tkuaUHMAlFR2YVNutdqjuVjKRl/o3iHktb4Xx+gVLP1oECOz3RQ6B6iHUswcIL952BdnG7pqGu8ZIEL6OV/ouhI1QXXvlIO+bAzqicEhIWyocQItpFVT0iMv5QdW2UYK2fhUOmmOAvq1QIDAQAB";
	    PublicKey PublicKey = loadPublicKey(publicKeyStr);*/
	    
	    String privateKeyStr = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKPxVU4xRsIuqt7kRQRCF4RfgUaMyGFQ9WRi1tz3mpG6P3GmFfRskoSm8/PD5wxHspeBGL/8vavxHWS/20jfQY9MEZEMDNMIN7vpgE6hI8bAv+22jtl5y7Bjm5Y4yRRj586z+yefHsUGgRypSsgznDATqsNPlCC4LbSTZoKvx62fAgMBAAECgYAtkqauB9Ctph9lunrdBipXZ90d6YDCXKj6cOddoY7cN7PvOcYcnhnUujxSZQDTTxL8PqzMoctwAqSzHwosJbOpWgcLKIXRD1GfLoIGygk+QNJxwqyxgw4gkKVdmtnbkv42UBubHeGeFAobVBsUIrQ+Ca+1ujVd+4Th13Emh6uAUQJBANCzqP8Wkvzb6KbDwZj8fa4FdsJv3DHvKIp9cuTfMu1/DkL77OfWm+hz1WSpFC2xmQyDeIjfgSTCZcGDR6pUAbMCQQDJGN2+FpNilYtBmGs/97qybxwFbUGwhq2UvdJikDkF2vn3R4YgWknOp79ML5jn3ihTtmgBbX0/kpQJIFRGe/ZlAkAr2BKAxHVMucY+gpGBWkns7Sjt4CIaO2wA7Cne+yTvz+lnGRXD/snyI6OI6hxbHRxSDKyd1JaE6nIGHVZI6i0RAkArJHaODXHZOJQDopt/wboABe5RC7uID5y1yHOWSbKyGuR9tI6F6ljjSQG1apC3TeYA76UoiUDRnrS7sH/kDzwxAkB1flszYFH0To4gD/8tCka0DHq+9+nQb2zZrkyubCGKH5aY2MkJd3rQJz+anGGgcY1slb/Er/I3z4KBHfTPjfvp";
        PrivateKey PrivateKey = loadPrivateKey(privateKeyStr);
        String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCj8VVOMUbCLqre5EUEQheEX4FGjMhhUPVkYtbc95qRuj9xphX0bJKEpvPzw+cMR7KXgRi//L2r8R1kv9tI30GPTBGRDAzTCDe76YBOoSPGwL/tto7ZecuwY5uWOMkUY+fOs/snnx7FBoEcqUrIM5wwE6rDT5QguC20k2aCr8etnwIDAQAB";
        PublicKey PublicKey = loadPublicKey(publicKeyStr);
	    
	    String str = "{\"code\":-1,\"error\":\"缺少参数\",\"message\":\"请将参数上传全\"}";
	    byte[] aa = encryptData(str.getBytes("UTF-8"), PublicKey);
	    String encryptData = Base64Utils.encode(aa);
	    byte[] bb = Base64Utils.decode(encryptData);
	    String deStr = new String(decryptData(bb, PrivateKey), "UTF-8");
	    System.out.println("加密后："+encryptData);
	    System.out.println("解密后："+deStr);
    }

}
